#Binary parser template

import os, sys, math
from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class CabalOnline_EBM(Model3D):
    
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(CabalOnline_EBM,self).__init__("EBM")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        
    def read_name(self):
        
        return self.inFile.read_string(self.inFile.read_ushort())
        
    def parse_bones(self):
        
        numBones = self.inFile.read_ushort()
        print("%d bones" %numBones)
        for i in xrange(numBones):
            boneName = self.read_name()
            parentIndex = self.inFile.read_ulong()
            boneMatrix = self.inFile.read_float(16)
            parentMatrix = self.inFile.read_float(16)
            
            self.create_bone(boneName)
            
    def parse_animation(self):
        
        numAnim = self.inFile.read_ushort()
        print "%d animations" %numAnim
        for i in xrange(numAnim):
            name = self.read_name()
            numBones = self.inFile.read_ushort()
            for j in xrange(numBones):
                boneName = self.read_name()
                numTranslate = self.inFile.read_ulong()
                for k in xrange(numTranslate):
                    keyFrameSec = self.inFile.read_float()
                    x, y, z = self.inFile.read_float(3)
                    keyFrameIndex = int(math.floor(keyFrameSec * 100))
            
                numRotate = self.inFile.read_ulong()
                for k in xrange(numRotate):
                    keyFrameSec = self.inFile.read_float()
                    x, y, z, w = self.inFile.read_float(4)
                    keyFrameIndex = int(math.floor(keyFrameSec * 100))
        
    def parse_texture(self, matNum):
        
        texName = self.read_name()
        texSize = self.inFile.read_ulong()
        texData = self.inFile.read(texSize)
        self.inFile.seek(26, 1)
        
        texture = open(texName, 'wb')
        texture.write(texData)
        texture.close()
        texName = texName.replace("dds", "png")
        self.add_texture_name(matNum, texName)
        self.add_material_name(matNum, texName)
    
    def parse_materials(self):
        
        numMat = self.inFile.read_ushort()
        print("%d materials" %numMat)
        for i in xrange(numMat):
            light = self.inFile.read_float(17)
            diffuse = light[0:4]
            ambient = light[4:8]
            specular = light[8:12]
            emissive = light[12:16]
            power = light[16]
            
            matName = "material[%d]" %i
            self.create_material(i)
            self.add_material_name(i, matName)
            self.parse_texture(i)
    
    def parse_vertices(self, meshName, numVerts):
        
        for i in xrange(numVerts):
            vx, vy, vz, nx, ny, nz, tu, tv = self.inFile.read_float(8)
            
            self.create_vertex(meshName, i)
            self.add_coords(meshName, i, [vx, vy, vz])
            self.add_vert_normals(meshName, i, [nx, ny, nz])
            self.add_vert_uv(meshName, i, [tu, tv])
    
    def parse_faces(self, meshName, numFaces, matNum):
        
        for i in xrange(numFaces):
            v1, v2, v3 = self.inFile.read_ushort(3)
            
            self.create_face(meshName, i)
            self.add_face_verts(meshName, i, [v1, v2, v3])
            self.add_face_material(meshName, i, matNum)
            
    def parse_mesh_weights(self):
        
        numWeights = self.inFile.read_ushort()
        numBones = self.bone_count()
        print("%d weights" %numWeights, self.inFile.tell())
        for i in xrange(numWeights):
        
            for j in xrange(numBones):
                count = self.inFile.read_ulong()
                boneID = self.inFile.read_ulong(count)
                weights = self.inFile.read_float(count)
    
    def parse_mesh(self):
        
        numMesh = self.inFile.read_ushort()
        for i in xrange(numMesh):
            meshName = self.read_name()
            print meshName
            self.create_object(meshName)
            worldMatrix = self.inFile.read_float(16)
            localMatrix = self.inFile.read_float(16)
            self.inFile.read_ulong()
            matNum = self.inFile.read_ubyte()
            numVerts, numFaces = self.inFile.read_ushort(2)
            self.parse_vertices(meshName, numVerts)
            self.parse_faces(meshName, numFaces, matNum)
            
            chunk = self.inFile.read_ulong()
            if chunk == 0x41470205:
                self.parse_mesh_weights()
            else:
                self.inFile.seek(-4, 1)
        
    def parse_file(self):
        '''Main parser method. Can be replaced'''
        
        filesize = self.inFile.filesize()
        idstring = self.inFile.read_long()
        self.inFile.read_ushort()
        self.inFile.read_ulong()
        bbMin = self.inFile.read_float(3)
        bbMax = self.inFile.read_float(3)
        self.inFile.read_ulong()
        
        while self.inFile.tell() != filesize:
            print self.inFile.tell()
            chunk = self.inFile.read_ulong()

            if chunk == 0x41470201:
                self.parse_materials()
            
            elif chunk == 0x41470202:
                self.parse_mesh()
            
            elif chunk == 0x41470203:
                self.parse_bones()
            
            elif chunk == 0x41470204:
                self.parse_animation()

def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = CabalOnline_EBM(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return ["\x03\xED\x03\x00", "\x03\xEE\x03\x00", "\x03\xEF\x03\x00"], \
           "EBM", "Cabal Online EBM"

if __name__ == '__main__':
    
    file1 = ""
    obj = read_file(file1)